/**
 * 
 */
package com.unbiz.common.convert.primitive;

import com.unbiz.common.StringUtil;
import com.unbiz.common.convert.ConvertException;
import com.unbiz.common.convert.ObjectConverter;
import com.unbiz.common.convert.TypeConverter;

/**
 * @author <a href="mailto:xuchen06@baidu.com">xuc</a>
 * @version create on 2014年7月28日 下午11:12:30
 */
public class DoubleConverter extends ObjectConverter<Double> implements TypeConverter<Double> {

    public DoubleConverter() {
        register(Double.class);
        register(double.class);
    }

    @Override
    public Double toConvert(String value) {
        return convert(value);
    }

    @Override
    public String fromConvert(Double value) {
        return String.valueOf(value);
    }

    public Double toConvert(Object value) {
        if (value.getClass() == Double.class) {
            return (Double) value;
        }
        if (value instanceof Number) {
            return Double.valueOf(((Number) value).doubleValue());
        }

        return convert(value.toString());
    }

    private Double convert(String value) {
    	 String stringValue = value.trim();
         if (StringUtil.startsWithChar(stringValue, '+')) {
             stringValue = stringValue.substring(1);
         }
        try {           
            return Double.valueOf(stringValue);
        } catch (NumberFormatException e) {
        	double d = parseDouble(stringValue);
        	return d;
            //throw new ConvertException(value, e);
        }
    }

	/**
	 * Converts to a double.
	 */
	public static double parseDouble(String s) {
		int len = s.length();

		int start = 0;

		int i = 0;
		int ch = 0;

		while (i < len && Character.isWhitespace(s.charAt(i))) {
			start++;
			i++;
		}

		if (i + 1 < len && s.charAt(i) == '0' && ((ch = s.charAt(i)) == 'x' || ch == 'X')) {

			double value = 0;

			for (i += 2; i < len; i++) {
				ch = s.charAt(i);

				if ('0' <= ch && ch <= '9')
					value = value * 16 + ch - '0';
				else if ('a' <= ch && ch <= 'z')
					value = value * 16 + ch - 'a' + 10;
				else if ('A' <= ch && ch <= 'Z')
					value = value * 16 + ch - 'A' + 10;
				else
					return value;
			}

			return value;
		}

		if (i < len && ((ch = s.charAt(i)) == '+' || ch == '-')) {
			i++;
		}

		for (; i < len && '0' <= (ch = s.charAt(i)) && ch <= '9'; i++) {
		}

		if (ch == '.') {
			for (i++; i < len && '0' <= (ch = s.charAt(i)) && ch <= '9'; i++) {
			}
		}

		if (ch == 'e' || ch == 'E') {
			int e = i++;

			if (i < len && (ch = s.charAt(i)) == '+' || ch == '-') {
				i++;
			}

			for (; i < len && '0' <= (ch = s.charAt(i)) && ch <= '9'; i++) {
			}

			if (i == e + 1)
				i = e;
		}

		if (i == 0)
			return 0;
		else if (i == len && start == 0)
			return Double.parseDouble(s);
		else
			return Double.parseDouble(s.substring(start, i));
	}
}
